home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Pascal / System / PBGetInfo INIT / PBGetCatInfo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-23  |  8.9 KB  |  294 lines  |  [TEXT/KAHL]

  1. #include "PBGetInfo.h"
  2.  
  3.  
  4.  
  5. /*
  6.     Okay, the trickiest part of the following is the use of code like this:
  7.     
  8.         lea.l        sysVRefNum,a1
  9.         movea.w        @sVRN,a0
  10.         movem.w        a0,(a1)
  11.  
  12.     The problem is that we need to remember certain things such as the dirID 
  13.     of the system folder, the system folder's parent dirID, etc., and we don't
  14.     really have access to globals (all local storage is allocated on the
  15.     stack when we're called).  To get around this problem, I've done some
  16.     assembly stuff in the middle of this routine, including leaving space
  17.     for storage of this pseudo-global data (by the way, this routine is
  18.     locked in the system heap, so it stays around between invocations).
  19.     
  20.     During the INIT sequence when this patch is installed, the INIT code
  21.     looks up the info we need and stores it in the appropriate place in
  22.     this routine (okay, so we're writing self-modifying code-- so sue me).
  23.     Later, when the routine is actually called by a user doing the
  24.     GetCatInfo A-Trap, we need to access the pseudo-global data, and the
  25.     easiest way to do this without having to write the whole thing in
  26.     assembler or use a lot of pointers is to copy the pseudo-global data
  27.     into the local variables which have been allocated on the stack as
  28.     part of the normal sequence of things (you need to understand how
  29.     the stack and local variables are handled on the Mac using registers
  30.     A6 and A7).  And that's what the code snippet does:
  31.     
  32.         lea.l        sysVRefNum,a1    ; get the address of the local variable 'sysVRefNum' and store it in register A1
  33.         movea.w        @sVRN,a0        ; now move the data stored in pseudo-global sVRN into register A0
  34.         movem.w        a0,(a1)            ; now move the contents of register A0 into the place pointed at by register A1
  35.  
  36.     Easy, no?  Well, sort of.
  37.     
  38.     There's probably a better way, but I'm not much of a Mac assembly programmer....
  39.     This way works, even if it is self-modifying and likely to break on a 68040
  40.     Mac with separate instruction and data caches (is there a flush-cache command
  41.     I can use?).
  42.     
  43. */
  44.  
  45.  
  46. int strcmp(char *s1, char *s2);
  47.  
  48.  
  49. void main(void)
  50. {
  51. int                errCode,selector,sysVRefNum,sysVolNum,index,*sysFolderIndex,*locked;
  52. long            sysFolderDirID,sysFolderParID,*lastMod;
  53. char            forbid;
  54. char            *lockMessage,*unlockMessage;
  55. CInfoPBRec        *paramBlock,myPBRec;
  56.  
  57.  
  58.     asm
  59.     {
  60.             movem.l        d0-d7/a0-a6,-(sp)    /* save registers */
  61.             
  62.             movem.w        d0,selector            /* move the A-Trap selector code to a local variable for easier access */
  63.             lea.l        paramBlock,a1        /* move the pointer to the paramater block to a local variable too */
  64.             movem.l        a0,(a1)
  65.             
  66.             lea.l        sysVRefNum,a1        /* move the system folder volume reference number (previously obtained during INIT execution at startup) into a local variable */
  67.             movea.w        @sVRN,a0
  68.             movem.w        a0,(a1)
  69.             
  70.             lea.l        sysVolNum,a1        /* move the previously-obtained system folder volume number into local storage */
  71.             movea.w        @sVNUm,a0
  72.             movem.w        a0,(a1)
  73.             
  74.             lea.l        locked,a1            /* is it locked or not? */
  75.             lea.l        @lockFlag,a0
  76.             movem.l        a0,(a1)
  77.             
  78.             lea.l        sysFolderDirID,a1    /* move the previously-obtained system folder dirID into local storage */
  79.             movea.l        @dirID,a0
  80.             movem.l        a0,(a1)
  81.             
  82.             lea.l        sysFolderParID,a1    /* move the previously-obtained system folder's parent folder dirID into local storage */
  83.             movea.l        @parID,a0
  84.             movem.l        a0,(a1)
  85.             
  86.             lea.l        sysFolderIndex,a1    /* this is the index position of the system folder in the directory (remember, GetCatInfo lets you index through the files/folders in a directory) */
  87.             lea.l        @sfIndex,a0
  88.             movem.l        a0,(a1)
  89.             
  90.             lea.l        lastMod,a1            /* watch for modifications, such as the system folder being moved */
  91.             lea.l        @modDat,a0
  92.             movem.l        a0,(a1)
  93.             
  94.             lea.l        lockMessage,a1        /* the CDEV can pass a secret message to this patch to tell it to lock/unlock the system folder */
  95.             lea.l        @lockMess,a0
  96.             movem.l        a0,(a1)
  97.             
  98.             lea.l        unlockMessage,a1    /* the CDEV can pass a secret message to this patch to tell it to lock/unlock the system folder */
  99.             lea.l        @unlockMess,a0
  100.             movem.l        a0,(a1)
  101.             
  102.             bra.s        @skip                /* skip over the following, which is just memory allocated for storage of our sort-of globals between calls to us */
  103.                                             /* by the way, this storage technique probably breaks on 68040 machines, since they have a data and instruction cache */
  104.                                             
  105.                                             
  106.             dc.b        magicWord            /* this special number is used to mark the start of the pseudo-global storage area (during the INIT installation stuff, all the pseudo-globals are set) */
  107.             
  108. oldTrap:    dc.l        0                    /* pseudo-global data begins! */
  109. sVRN:        dc.w        0
  110. sVNUm:        dc.w        0
  111. dirID:        dc.l        0
  112. parID:        dc.l        0
  113. lockFlag:    dc.w        0
  114.  
  115. modDat:        dc.l        0
  116. sfIndex:    dc.w        0xFFFF
  117. lockMess:    dc.b        LOCKMESSAGE,0
  118. unlockMess:    dc.b        UNLOCKMESSAGE,0
  119.             dc.b        0                    /* pseudo-globals end! */
  120.  
  121. skip:        nop                    
  122.     }
  123.     
  124.     /* watch for the secret message from the CDEV */
  125.     
  126.     if (paramBlock->hFileInfo.ioVRefNum == 0 && paramBlock->hFileInfo.ioDirID == 0 && paramBlock->hFileInfo.ioFDirIndex == 0 && paramBlock->hFileInfo.ioNamePtr)
  127.     {
  128.         if (strcmp((char *) paramBlock->hFileInfo.ioNamePtr,lockMessage) == EQSTR)
  129.         {
  130.             *locked = TRUE;
  131.             
  132.             paramBlock->hFileInfo.ioResult = noErr;
  133.             
  134.             asm
  135.             {
  136.                     movem.l        (sp)+,d0-d7/a0-a6    /* restore registers */
  137.                     unlk        a6                    /* clean up the stack */
  138.                     move.w        #noErr,d0            /* E.T. go home */
  139.                     rts
  140.             }
  141.         }
  142.         
  143.         else if (strcmp((char *) paramBlock->hFileInfo.ioNamePtr,unlockMessage) == EQSTR)
  144.         {
  145.             *locked = FALSE;
  146.             
  147.             paramBlock->hFileInfo.ioResult = noErr;
  148.             
  149.             asm
  150.             {
  151.                     movem.l        (sp)+,d0-d7/a0-a6    /* restore registers */
  152.                     unlk        a6                    /* clean up the stack */
  153.                     move.w        #noErr,d0            /* E.T. go home */
  154.                     rts
  155.             }
  156.         }
  157.     }
  158.     
  159.     forbid = FALSE;
  160.     
  161.     /* check for indexed GetCatInfo calls */
  162.     
  163.     if (*locked && selector == 9 && paramBlock->hFileInfo.ioFDirIndex > 0)
  164.     {
  165.         /* check to see if the number of entries in the system folder's parent folder has changed, and if so, get the new index position of the system folder */
  166.         
  167.         if (paramBlock->hFileInfo.ioVRefNum == sysVolNum && paramBlock->hFileInfo.ioDirID == sysFolderParID)
  168.         {
  169.             myPBRec.dirInfo.ioCompletion = 0L;
  170.             myPBRec.dirInfo.ioNamePtr = 0L;
  171.             myPBRec.dirInfo.ioVRefNum = 0;
  172.             myPBRec.dirInfo.ioFDirIndex = -1;
  173.             myPBRec.dirInfo.ioDrDirID = sysFolderParID;
  174.             
  175.             asm
  176.             {
  177.                 lea.l        myPBRec,a0        /* call the old GetCatInfo */
  178.                 move.w        #9,d0
  179.                 movea.l        @oldTrap,a1
  180.                 jsr            (a1)
  181.                 
  182.                 lea.l        errCode,a0        /* move the result into local storage */
  183.                 movem.w        d0,(a0)
  184.             }
  185.             
  186.             
  187.             if (errCode != noErr)
  188.                 *sysFolderIndex = -1;        /* oops, an error occurred! */
  189.             
  190.             else
  191.             {
  192.                 if (myPBRec.dirInfo.ioDrMdDat > *lastMod)        /* oh ho!  the parent folder has been modified since we last checked it! */
  193.                 {
  194.                     *lastMod = myPBRec.dirInfo.ioDrMdDat;
  195.                     
  196.                     index = 1;
  197.                     
  198.                     /* now search through the folder to find the index position of the system folder */
  199.                     
  200.                     do
  201.                     {
  202.                         myPBRec.dirInfo.ioCompletion = 0L;
  203.                         myPBRec.dirInfo.ioNamePtr = 0L;
  204.                         myPBRec.dirInfo.ioVRefNum = -1;
  205.                         myPBRec.dirInfo.ioFDirIndex = index;
  206.                         myPBRec.dirInfo.ioDrDirID = sysFolderParID;
  207.                         
  208.                         asm
  209.                         {
  210.                             lea.l        myPBRec,a0
  211.                             move.w        #9,d0
  212.                             movea.l        @oldTrap,a1
  213.                             jsr            (a1)
  214.                             
  215.                             lea.l        errCode,a0
  216.                             movem.w        d0,(a0)
  217.                         }
  218.                         
  219.                         if (errCode == noErr && myPBRec.dirInfo.ioDrDirID == sysFolderDirID)
  220.                         {
  221.                             *sysFolderIndex = index;    /* found the new position of the system folder! */
  222.                             errCode = fnfErr;            /* stop indexing */
  223.                         }
  224.                         
  225.                         else
  226.                             index++;
  227.                         
  228.                     } while (errCode == noErr);
  229.                     
  230.                     if (errCode != fnfErr)
  231.                         *sysFolderIndex = -1;
  232.                 }
  233.             }
  234.             
  235.             /* if the caller is searching the system folder's parent folder, we may have to bump the index by one to skip over the system folder */
  236.             
  237.             if (*sysFolderIndex > 0 && paramBlock->hFileInfo.ioFDirIndex >= *sysFolderIndex)
  238.                     paramBlock->hFileInfo.ioFDirIndex += 1;
  239.         }
  240.         
  241.         /* is the caller searching the system folder using a working directory reference number? */
  242.         
  243.         else if (paramBlock->hFileInfo.ioVRefNum == sysVRefNum)
  244.             forbid = TRUE;
  245.         
  246.         /* is the caller searching the system folder using a dirID? */
  247.         
  248.         else if (paramBlock->hFileInfo.ioDirID == sysFolderDirID)
  249.             forbid = TRUE;
  250.     }
  251.     
  252.     if (forbid)
  253.     {
  254.         SysBeep(1);        /* beep to indicate that we've denied access */
  255.         
  256.         paramBlock->hFileInfo.ioResult = ioErr;
  257.         
  258.         asm
  259.         {
  260.                 movem.l        (sp)+,d0-d7/a0-a6    /* restore registers */
  261.                 unlk        a6                    /* clean up stack frame */
  262.                 move.w        #ioErr,d0            /* return an error, since we're not allowing the caller to peek into the system folder */
  263.                 rts
  264.         }
  265.     }
  266.     
  267.     else
  268.     {
  269.         asm 
  270.         {
  271.                 movem.l        (sp)+,d0-d7/a0-a6    /* restore registers */
  272.                 unlk        a6                    /* clean up stack frame */
  273.                 move.l        @oldTrap,-(sp)        /* jump to the old trap, since the caller is looking somewhere other than the system folder, or the system folder is unlocked */
  274.                 rts
  275.         }
  276.     }
  277. }
  278.  
  279.  
  280.  
  281. int strcmp(char *s1, char *s2)
  282. {
  283.     while(*s1 == *s2 && *s2 && *s1)
  284.     {
  285.         s1++; 
  286.         s2++;
  287.     }
  288.     
  289.     if (*s1 == *s2) 
  290.         return(EQSTR);
  291.     else
  292.         return(!EQSTR);
  293. }
  294.